﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "ActionBarDialog.h"
#include "FindByIdPredicate.h"
#include "GbmpNew.h"
#include <QVBoxLayout>
#include <QRadioButton>
#include <QMoveEvent>
#include "OwnerPtr.h"
#include "IApplication.h"
#include "IApplicationWindow.h"
#include "IUiDocumentViewManager.h"
#include "IUiView.h"
#include "GmStyleSheetHelper.h"
#include "ILineEditDefinition.h"
#include "QtLineEdit.h"
#include "ILabelDefinition.h"
#include "QtLabel.h"
#include "ICheckBoxGroupDefinition.h"
#include "QtCheckBoxGroup.h"
#include "qcheckbox.h"
#include "IRadioButtonGroupDefinition.h"
#include "QtRadioButtonGroup.h"
#include "IComboBoxDefinition.h"
#include "QtComboBox.h"
#include "IControlDefinitionLibrary.h"
#include "qgroupbox.h"
#include "ActionInputEvent.h"
#include "IComboBoxEventHandler.h"
#include "ILineEditEventHandler.h"
#include "IRadioButtonGroupEventHandler.h"
#include "ICheckBoxGroupEventHandler.h"
#include "IComboBoxEventArgs.h"
#include "IComboBoxEvent.h"
#include "ICheckBoxGroupEventArgs.h"
#include "ICheckBoxGroupEvent.h"
#include "IRadioButtonGroupEventArgs.h"
#include "IRadioButtonGroupEvent.h"
#include "ILineEditEvent.h"
#include "ILineEditEventArgs.h"

#include "QMainWindow.h"
#include "GUiBaseInterfaceEnums.h"

#include "GcmpUiDocumentImpl.h"

#include "LineEditEvent.h"  ///// TODO:
#include "LineEditEventArgs.h"  ///// TODO:


#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
namespace
{
    std::pair<std::wstring, gcmp::Any> GetMessage(const ILineEditDefinition* pDefine1)
    {
        std::pair<std::wstring, gcmp::Any> message;
        DBG_WARN_AND_RETURN_UNLESS(pDefine1, message, L"pDefine1为空",L"GDMPLab",L"2024-03-30");
        message.first = pDefine1->GetId();

        if (pDefine1->GetInputType() == LineEditInputType::InputString)
        {
            message.second = pDefine1->GetText();
        }
        else if (pDefine1->GetInputType() == LineEditInputType::InputInt)
        {
            message.second = StringUtil::ToNumber<int>(pDefine1->GetText());
        }
        else if (pDefine1->GetInputType() == LineEditInputType::InputDouble)
        {
            message.second = StringUtil::ToNumber<double>(pDefine1->GetText());
        }
        return message;
    }

    class ActionDlgComboBoxHandler : public IComboBoxEventHandler
    {
    public:
        ActionDlgComboBoxHandler(ActionInputEvent* inputEvent)
            :m_inputEvent(inputEvent)
        {

        }
        virtual void On(IComboBoxEventArgs* pArgs) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
            const IEvent* pEvent = pArgs->GetEvent();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pEvent, L"pEvent为空",L"GDMPLab",L"2024-03-30");
            const IComboBoxEvent* pControlEvent = dynamic_cast<const IComboBoxEvent*>(pEvent);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pControlEvent, L"pComboBoxEvent为空",L"GDMPLab",L"2024-03-30");
            IComboBoxDefinition* pDefine1 = pControlEvent->GetSender();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDefine1, L"pDefine1为空",L"GDMPLab",L"2024-03-30");
            // 构造消息。
            std::pair<std::wstring, gcmp::Any> message;
            message.first = pDefine1->GetId();
            message.second = pDefine1->GetCurrentIndex();//发送选项结果

            DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
            ActionInputEventArgs inputArgs(ActionInputEventType::InputValueChanged, message);
            m_inputEvent->Emit(&inputArgs);
        }
    public:
        gcmp::ActionInputEvent*  m_inputEvent;
    };

    class ActionDlgCheckBoxGroupHandler : public ICheckBoxGroupEventHandler
    {
    public:
        ActionDlgCheckBoxGroupHandler(ActionInputEvent* inputEvent)
            :m_inputEvent(inputEvent)
        {

        }
        virtual void On(ICheckBoxGroupEventArgs* pArgs) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
            const IEvent* pEvent = pArgs->GetEvent();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pEvent, L"pEvent为空",L"GDMPLab",L"2024-03-30");
            const ICheckBoxGroupEvent* pControlEvent = dynamic_cast<const ICheckBoxGroupEvent*>(pEvent);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pControlEvent, L"pComboBoxEvent为空",L"GDMPLab",L"2024-03-30");
            ICheckBoxGroupDefinition* pDefine1 = pControlEvent->GetSender();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDefine1, L"pDefine1为空",L"GDMPLab",L"2024-03-30");
            std::pair<std::wstring, CheckState> state = pArgs->GetStateChangedCheckBoxIdAndState();
            // 构造消息。
            std::pair<std::wstring, gcmp::Any> message;
            message.first = pDefine1->GetId() + L"_" + state.first;
            message.second = state.second == CheckState::Checked ? true : false;//发送选项结果

            DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
            ActionInputEventArgs inputArgs(ActionInputEventType::InputValueChanged, message);
            m_inputEvent->Emit(&inputArgs);
        }
    public:
        gcmp::ActionInputEvent*  m_inputEvent;
    };

    class ActionDlgRadioGroupHandler : public IRadioButtonGroupEventHandler
    {
    public:
        ActionDlgRadioGroupHandler(ActionInputEvent* inputEvent)
            :m_inputEvent(inputEvent)
        {

        }
        virtual void On(IRadioButtonGroupEventArgs* pArgs) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
            const IEvent* pEvent = pArgs->GetEvent();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pEvent, L"pEvent为空",L"GDMPLab",L"2024-03-30");
            const IRadioButtonGroupEvent* pControlEvent = dynamic_cast<const IRadioButtonGroupEvent*>(pEvent);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pControlEvent, L"pComboBoxEvent为空",L"GDMPLab",L"2024-03-30");
            IRadioButtonGroupDefinition* pDefine1 = pControlEvent->GetSender();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDefine1, L"pDefine1为空",L"GDMPLab",L"2024-03-30");
            // 构造消息。
            std::pair<std::wstring, gcmp::Any> message;
            message.first = pDefine1->GetId();
            message.second = pDefine1->GetCurrentRadioButton();//发送选项结果

            DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
            ActionInputEventArgs inputArgs(ActionInputEventType::InputValueChanged, message);
            m_inputEvent->Emit(&inputArgs);
        }
    public:
        gcmp::ActionInputEvent*  m_inputEvent;
    };

    class ActionDlgLineEditHandler : public ILineEditEventHandler
    {
    public:
        ActionDlgLineEditHandler(ActionInputEvent* inputEvent)
            :m_inputEvent(inputEvent)
        {

        }
        virtual void On(ILineEditEventArgs* pArgs) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");

            const IEvent* pEvent = pArgs->GetEvent();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pEvent, L"pEvent为空",L"GDMPLab",L"2024-03-30");
            const ILineEditEvent* pControlEvent = dynamic_cast<const ILineEditEvent*>(pEvent);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pControlEvent, L"pComboBoxEvent为空",L"GDMPLab",L"2024-03-30");
            ILineEditDefinition* pDefine1 = pControlEvent->GetSender();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDefine1, L"pDefine1为空",L"GDMPLab",L"2024-03-30");
            // 构造消息。
            std::pair<std::wstring, gcmp::Any> message = GetMessage(pDefine1);


            DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
            ActionInputEventArgs inputArgs(ActionInputEventType::InputValueChanged, message);
            m_inputEvent->Emit(&inputArgs);
        }
    public:
        gcmp::ActionInputEvent*  m_inputEvent;
    };

    QWidget* getCurrentUiViewQWidget()
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(IUiDocumentViewManager::Get(), L"IUiDocumentViewManager==nullptr",L"GDMPLab",L"2024-03-30");
        gcmp::IUiView* pUIView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUIView != nullptr, L"pUIView==nullptr",L"GDMPLab",L"2024-03-30");
        QWidget* pViewWidget = QWidget::find((WId)pUIView->GetUiViewId());
        return pViewWidget;
    }
}


ActionBarDialog::ActionBarDialog(QWidget *parent) :
    QDialog(parent, Qt::FramelessWindowHint | Qt::SubWindow), m_isMoving(false), m_pQHBoxLayout(nullptr), m_pAction(nullptr)
{
    setModal(false);//设置非模态
    setObjectName("ActionInputDlg");
    std::wstring styleSheetStr = GmStyleSheetHelper::Instance()->GetCurrentStyleData();
    setStyleSheet(QString::fromStdWString(styleSheetStr));
    this->setProperty("use_gbmp_title", true);
    //根据内容自动调整对话框大小
    adjustSize();
    installEventFilter(this);
    m_inputEvent = NEW_AS_OWNER_PTR(ActionInputEvent, L"ActionInputEvent", this);
    this->setMaximumHeight(32);
    this->setMinimumHeight(32);

    if (parent)
    {
        parent->installEventFilter(this);
    }

}

ActionBarDialog::~ActionBarDialog()
{
    m_wpControls.clear();
}

void ActionBarDialog::Clear()
{
    QLayout* pLayout = layout();
    if (pLayout != nullptr)
    {
        for (auto& pControl : m_wpControls)
        {
            if (QWidget* pWidget = dynamic_cast<QWidget*>(pControl.Get()))
            {
                pLayout->removeWidget(pWidget); // remove from layout

                pWidget->deleteLater();//避免对话框上子控件重影
                pWidget->hide(); //触发日志记录正常
            }
            else if (QButtonGroup* pButtonGroup = dynamic_cast<QButtonGroup*>(pControl.Get()))
            {
                QList<QAbstractButton*> buttons = pButtonGroup->buttons();
                for (auto button : buttons)
                {
                    pLayout->removeWidget(button); // remove from layout

                    button->deleteLater();//避免对话框上子控件重影
                    button->hide(); //触发日志记录正常
                }
            }
        }

        m_wpControls.clear();
        pLayout->invalidate();
    }

    adjustSize();
}

void ActionBarDialog::SetDialogLayout(QHBoxLayout* pLayout)
{
    if (pLayout != nullptr)
    {
        m_pQHBoxLayout = pLayout;
    }
}

// do not add new_control into layout, but add to m_wpControls to manage resource
template<typename ControlType, typename ControlDefinitionType>
ControlType* ActionBarDialog::AddControl(OwnerPtr<ControlDefinitionType> pControlDefinition)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pControlDefinition, L"pControlDefinition是空指针",L"GDMPLab",L"2024-03-30");

    const std::wstring id = pControlDefinition->GetId();
    auto search = std::find_if(m_wpControls.begin(), m_wpControls.end(), FindControlPtrByIdPredicate<WeakPtr<IControl>>(id));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(search == m_wpControls.end(), L"对话框已经添加了控件" + id,L"GDMPLab",L"2024-03-30");
    OwnerPtr<ControlDefinitionType> *pOwnerPtr = &pControlDefinition;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pOwnerPtr, L"pOwnerPtr是空指针",L"GDMPLab",L"2024-03-30");
    ControlType *pControlType = NEW_AS_QT(ControlType, TransferOwnership(*pOwnerPtr),this);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pControlType, L"pControlType是空指针",L"GDMPLab",L"2024-03-30");

    // add to layout
    if (QHBoxLayout* pQHBoxLayout = GetDialogLayout())
    {
        pQHBoxLayout->addWidget(pControlType);
    }
    m_wpControls.emplace_back(pControlType);
    return pControlType;
}

// do not add new_control into layout, but add to m_wpControls to manage resource

template<typename ControlGroupType, typename ControlType, typename ControlGroupDefineType>
IControl* ActionBarDialog::AddControlGroup(OwnerPtr<ControlGroupDefineType> pControlGroupDefine, bool needAddSepartor)
{
    static_assert(std::is_base_of<QWidget, ControlType>::value, "ControlType must derive from QWidget");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pControlGroupDefine, L"pControlDefinition是空指针",L"GDMPLab",L"2024-03-30");

    const std::wstring& id = pControlGroupDefine->GetId();
    auto search = std::find_if(m_wpControls.begin(), m_wpControls.end(), FindControlPtrByIdPredicate<WeakPtr<IControl>>(id));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(search == m_wpControls.end(), L"Panel上已经添加了控件" + id,L"GDMPLab",L"2024-03-30");

    ControlGroupType* pControlGroup = nullptr;
    if (needAddSepartor)
    {
        QHBoxLayout* pQHBoxLayout = GetDialogLayout();
        QFrame *spilterLine = NEW_AS_QT(QFrame,this);
        spilterLine->setFrameShape(QFrame::VLine);
        spilterLine->setFrameShadow(QFrame::Sunken);
        pQHBoxLayout->addWidget(spilterLine);
    }
    {

        auto pDefine = pControlGroupDefine.get();
        OwnerPtr<ControlGroupDefineType> *pOwnerPtr = &pControlGroupDefine;
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pOwnerPtr, L"pOwnerPtr是空指针",L"GDMPLab",L"2024-03-30");
        pControlGroup = NEW_AS_QT(ControlGroupType, TransferOwnership(*pOwnerPtr), this);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pControlGroup, L"pControlGroup是空指针",L"GDMPLab",L"2024-03-30");
        std::vector<ControlType*> controls = pControlGroup->GetAllControls();
        if (controls.size() > 1)
        {
            std::wstring title = pDefine->GetCaption();
            AddLabel(title + L"Label", title, title);
        }

        for (auto pControl : controls)
        {
            QWidget* pWidget = qobject_cast<QWidget*>(pControl);
            DBG_WARN_AND_CONTINUE_UNLESS(pWidget, L"pWidget为空",L"GDMPLab",L"2024-03-30");

            if (QHBoxLayout* pQHBoxLayout = GetDialogLayout())
                pQHBoxLayout->addWidget(pControl);
        }
    }

    m_wpControls.emplace_back(pControlGroup);
    return pControlGroup;
}

IControl* ActionBarDialog::AddLabel(const std::wstring& name, const std::wstring& caption, const std::wstring& tooltip)
{
    OwnerPtr<ILabelDefinition> pLabelDef = ILabelDefinition::Create(name, caption, L"");
    return AddControl<QtLabel, ILabelDefinition>(TransferOwnership(pLabelDef));
}

void ActionBarDialog::onMoveRequested(const QPoint& cursorPos, const QPoint& offset)
{
    Q_UNUSED(cursorPos);
    move(pos() + offset);
}

void ActionBarDialog::ResetPosition()
{
    //return
    IApplicationWindow* pUIMainWnd = IApplication::Get()->GetApplicationWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIMainWnd, L"pUIMainWnd不应为空",L"GDMPLab",L"2024-03-30");

    gcmp::IUiView * pCurUIView = IUiDocumentViewManager::Get()->GetCurrentUiView();
    if (!pCurUIView)
    {
        return;
    }

    QWidget * pCurViewWidget = QWidget::find((WId)pCurUIView->GetUiViewId());
    if (!pCurViewWidget || !parentWidget())
    {
        return;
    }

    QWidget * pDlgParent = parentWidget();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDlgParent, L"pDlgParent不应为空",L"GDMPLab",L"2024-03-30");
    bool isActive = false;  
    bool isWindow = false; 
    bool isMinimized = false; 
    isWindow = pDlgParent->isWindow();
    isActive = pDlgParent->isActiveWindow();
    isMinimized = pDlgParent->isMinimized();
    
    QList<QWidget*> listWidget = pDlgParent->findChildren<QWidget*>(pCurViewWidget->objectName());
    QList<QWidget*> ::ConstIterator listIter;
    for (listIter = listWidget.constBegin(); listIter != listWidget.constEnd(); ++listIter) 
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(*listIter, L"listIter不应为空",L"GDMPLab",L"2024-03-30");
        if (pCurViewWidget == (*listIter))
        {
            break;
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(listIter!=listWidget.constEnd(), L"parentWidget不是pCurViewWidget的父类",L"GDMPLab",L"2024-03-30");
    
    QPoint curViewGlobalPosOrigin = pCurViewWidget->mapTo(pDlgParent, QPoint(0, 0));

    //ActionInputDialog后续会废弃，因此激活视口时，未增加其位置计算的操作
    if (pCurUIView->IsSubUiView())
    {
        IUiView* pParentUiView = nullptr;
        QVariant qtVar = pDlgParent->property("uiView");
        if (qtVar.isValid()) {
            pParentUiView = static_cast<gcmp::IUiView*>(qtVar.value<void*>());
        }
        if (pParentUiView)
            curViewGlobalPosOrigin = pDlgParent->mapToParent(QPoint(0, 0));
    }

    int applyOrCancelWidgetWidth = 0;

    curViewGlobalPosOrigin.setX(curViewGlobalPosOrigin.x() + applyOrCancelWidgetWidth);

    move(curViewGlobalPosOrigin);
    // 显示到视图的上面
    raise();
    show();
    int thisWidth = width();
    int parentWidth = pCurViewWidget->width();
    /*  if (thisWidth>parentWidth)
      {
          DBG_WARN(L"超出父窗口",L"GDMPLab",L"2024-03-30");
      }*/
}

void ActionBarDialog::DestroyDialog()
{
    QWidget * pParent = parentWidget();   //手动删除控件事件过滤器，防止Qt继续调用
    if (pParent)
    {
        pParent->removeEventFilter(this);      
    }

    removeEventFilter(this);
    setVisible(false);    //设置为不可见，否则isActiveWindow()可能返回true，日志回放时会出错
    deleteLater();       //将dialog交给Qt进行释放，平台不再管理
}

void ActionBarDialog::InitDlg(const std::wstring& title, std::vector<OwnerPtr<IControlDefinition>>&& dlgCtrlDefines, IAction* pAction)
{
    m_pAction = pAction;


    // 清理原有控件
    QHBoxLayout* pQHBoxLayout = GetDialogLayout();
    if (pQHBoxLayout != nullptr)
    {
        Clear();
    }
    else
    {
        //添加布局器
        pQHBoxLayout = NEW_AS_QT_CHILD(QHBoxLayout, this);
        setLayout(pQHBoxLayout);
        SetDialogLayout(pQHBoxLayout);
        //修改布局器默认边框距离(11,11,11,11)为如下
        pQHBoxLayout->setContentsMargins(6, 6, 6, 6);
        pQHBoxLayout->setSizeConstraint(QLayout::SizeConstraint::SetDefaultConstraint);
    }

    AddLabel(title + L"Label", title, title);
    QFrame *spilterLine = NEW_AS_QT(QFrame,this);
    spilterLine->setFrameShape(QFrame::VLine);
    spilterLine->setFrameShadow(QFrame::Sunken);
    pQHBoxLayout->addWidget(spilterLine);
    bool needAddSepartor = false;
    bool hasGroupBefore = false;
    for (auto& pCtrlDef : dlgCtrlDefines)
    {
        if (pCtrlDef == nullptr)
            continue;

        const std::wstring& caption = pCtrlDef->GetCaption();
        DBG_WARN_UNLESS(caption != L"", L"缺少提示信息",L"GDMPLab",L"2024-03-30");

        const std::wstring& ctrlDefName = pCtrlDef->GetId();
        if (const ILineEditDefinition* pLineEditDef = dynamic_cast<const ILineEditDefinition*>(pCtrlDef.get()))
        {
            if (hasGroupBefore)
            {
                QFrame *spilterLine = NEW_AS_QT(QFrame,this);
                spilterLine->setFrameShape(QFrame::VLine);
                spilterLine->setFrameShadow(QFrame::Sunken);
                pQHBoxLayout->addWidget(spilterLine);
            }
            // create a label
            AddLabel(ctrlDefName + L"Label", caption, caption);

          
            OwnerPtr<ILineEditEventHandler> pActionDlgLineEditHandler = NEW_AS_OWNER_PTR(ActionDlgLineEditHandler, m_inputEvent.get());
            pLineEditDef->GetEvent()->Add(pActionDlgLineEditHandler.get());
            m_lineEditHandler.push_back(TransferOwnership(pActionDlgLineEditHandler));
            if (QWidget* pLineEditWidget = AddControl<QtLineEdit, ILineEditDefinition>(TransferOwnershipCast<ILineEditDefinition>(pCtrlDef)))
            {
                QtLineEdit* pLineEdit = dynamic_cast<QtLineEdit*>(pLineEditWidget);

                QObject::connect(pLineEditWidget, SIGNAL(returnPressed()), this, SLOT(OnEditEnterPressed()), Qt::QueuedConnection);
            }
            hasGroupBefore = false;
            needAddSepartor = true;
        }
        else if (const ICheckBoxGroupDefinition* pChBoxGroupDef = dynamic_cast<const ICheckBoxGroupDefinition*>(pCtrlDef.get()))
        {
            OwnerPtr<ICheckBoxGroupEventHandler> pActionDlgCheckBoxGroupHandler = NEW_AS_OWNER_PTR(ActionDlgCheckBoxGroupHandler, m_inputEvent.get());
            pChBoxGroupDef->GetEvent()->Add(pActionDlgCheckBoxGroupHandler.get());
            m_checkBoxGroupHandler.push_back(TransferOwnership(pActionDlgCheckBoxGroupHandler));

            AddControlGroup<QtCheckBoxGroup, QCheckBox, ICheckBoxGroupDefinition>(TransferOwnershipCast<ICheckBoxGroupDefinition>(pCtrlDef), needAddSepartor);
            hasGroupBefore = true;
            needAddSepartor = true;
        }
        else if (const IRadioButtonGroupDefinition* pRadioButtonGroupDefine = dynamic_cast<const IRadioButtonGroupDefinition*>(pCtrlDef.get()))
        {
            OwnerPtr<IRadioButtonGroupEventHandler> pActionDlgIRadioGroupHandler = NEW_AS_OWNER_PTR(ActionDlgRadioGroupHandler, m_inputEvent.get());
            pRadioButtonGroupDefine->GetEvent()->Add(pActionDlgIRadioGroupHandler.get());
            m_radioButtonGroupHandler.push_back(TransferOwnership(pActionDlgIRadioGroupHandler));

            AddControlGroup<QtRadioButtonGroup, QRadioButton, IRadioButtonGroupDefinition>(TransferOwnershipCast<IRadioButtonGroupDefinition>(pCtrlDef), needAddSepartor);
            hasGroupBefore = true;
            needAddSepartor = true;
        }
        else if (const IComboBoxDefinition* pComboBoxDefine = dynamic_cast<const IComboBoxDefinition*>(pCtrlDef.get()))
        {
            // create a label
            if (hasGroupBefore)
            {
                QFrame *spilterLine = NEW_AS_QT(QFrame,this);
                spilterLine->setFrameShape(QFrame::VLine);
                spilterLine->setFrameShadow(QFrame::Sunken);
                pQHBoxLayout->addWidget(spilterLine);
            }
            AddLabel(ctrlDefName + L"Label", caption, caption);
           
            OwnerPtr<IComboBoxEventHandler> pActionDlgComboBoxHandler = NEW_AS_OWNER_PTR(ActionDlgComboBoxHandler, m_inputEvent.get());
            pComboBoxDefine->GetEvent()->Add(pActionDlgComboBoxHandler.get());
            m_comboBoxHandler.push_back(TransferOwnership(pActionDlgComboBoxHandler));

            AddControl<QtComboBox, IComboBoxDefinition>(TransferOwnershipCast<IComboBoxDefinition>(pCtrlDef));
            hasGroupBefore = false;
            needAddSepartor = true;
        }
    }
    adjustSize();
    ResetPosition();

}

//鼠标离开对话框，通知Action
void ActionBarDialog::leaveEvent(QEvent * event)
{   //鼠标离开对话框，通知所有LineEdit完成编辑
    for (auto& control : m_wpControls)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(control, L"control为空",L"GDMPLab",L"2024-03-30");
        ILineEditDefinition* pLineEditDef = dynamic_cast<ILineEditDefinition*>(control->GetControlDefinition());
        if (!pLineEditDef)
        {
            continue;
        }
        LineEditEvent* ctrlEvent = dynamic_cast<LineEditEvent*>(pLineEditDef->GetEvent());
        if (ctrlEvent)
        {
            LineEditEventArgs args(LineEditEventType::EditingFinished, pLineEditDef->GetId(), pLineEditDef->GetText());
            ctrlEvent->Emit(&args);
        }
    }

    std::pair<std::wstring, gcmp::Any> message;
    ActionInputEventArgs inputArgs(ActionInputEventType::InputMouseLeave, message);
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
    m_inputEvent->Emit(&inputArgs);
}

void ActionBarDialog::OnEditEnterPressed()
{
    if (QtLineEdit* pQtLineEdit = dynamic_cast<QtLineEdit*>(sender()))
    {
        IControlDefinition* pDefine = pQtLineEdit->GetControlDefinition();
        ILineEditDefinition* pLineEditDefine1 = dynamic_cast<ILineEditDefinition*>(pDefine);
        // 构造消息
        std::pair<std::wstring, gcmp::Any> message = GetMessage(pLineEditDefine1);

        // 发送消息
        ActionInputEventArgs inputArgs(ActionInputEventType::InputEnterFinished, message);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_inputEvent, L"m_inputEvent为空",L"GDMPLab",L"2024-03-30");
        m_inputEvent->Emit(&inputArgs);

        //// TODO:临时直接调用ActionManager结束Action处理，避免在Action事件中结束ActionInputDlg并回到对话框事件
        //ActionManager::GetInstance()->EndActionAndStartDefaultAction(GetAction());
    }
}

//重写鼠标按下事件
void ActionBarDialog::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_isMoving = true;
        m_movePosition = event->globalPos() - pos();
    }
    return QDialog::mousePressEvent(event);
}

//重写鼠标移动事件
void ActionBarDialog::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isMoving && (event->buttons() && Qt::LeftButton))
    {
        move(event->globalPos() - m_movePosition);
    }

    return QDialog::mouseMoveEvent(event);
}
void ActionBarDialog::mouseReleaseEvent(QMouseEvent *event)
{
    m_isMoving = false;

    return QDialog::mouseReleaseEvent(event);
}
void ActionBarDialog::moveEvent(QMoveEvent *event)
{
   /* return QDialog::moveEvent(event);*/
}

void ActionBarDialog::keyPressEvent(QKeyEvent *pEvent)
{
    QWidget* pViewWidget = getCurrentUiViewQWidget();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pViewWidget != nullptr, L"pViewWidget为空",L"GDMPLab",L"2024-03-30");

    switch (pEvent->key())
    {
    case Qt::Key_Return:
    case Qt::Key_Escape:
    case Qt::Key_Enter:
    {
        QApplication::sendEvent(pViewWidget, (QEvent*)pEvent);
        break;
    }

    default:
        QDialog::keyPressEvent(pEvent);
    }

}

void ActionBarDialog::SetWindowTitle(const std::wstring& strTitle)
{
    this->setWindowTitle(QString::fromStdWString(strTitle));
}

void ActionBarDialog::SetFocusToCurrentView()
{
    QWidget* pViewWidget = getCurrentUiViewQWidget();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pViewWidget != nullptr, L"pViewWidget为空",L"GDMPLab",L"2024-03-30");
    if (pViewWidget)
    {
        pViewWidget->setFocus();
    }
}

bool ActionBarDialog::eventFilter(QObject *object, QEvent *event)
{
    if (!isVisible())
        return false;

    // 拦截父窗口事件
    if (parent() == object)
    {
        if (dynamic_cast<QMoveEvent*>(event) || dynamic_cast<QWindowStateChangeEvent*>(event))
        {
            ResetPosition();
        }
        return false;
    }

    if (event && event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Tab)
        {
            QWidget* pViewWidget = getCurrentUiViewQWidget();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pViewWidget != nullptr, L"pViewWidget为空",L"GDMPLab",L"2024-03-30");
            // Tab 键转发给视图，用于snap对象的切换
            QApplication::sendEvent(pViewWidget, event);

            return true;
        }
    }
    return false;
}

bool ActionBarDialog::focusNextPrevChild(bool next)
{
    return false;
}

IActionInputEvent* ActionBarDialog::GetInputEvent()
{
    return m_inputEvent.get();
}

IAction* ActionBarDialog::GetAction()
{
    return m_pAction;
}